package net.xo68.destiny.starter.worker.handler.impl;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import net.xo68.destiny.contract.domain.report.DatagramSerializer;
import net.xo68.destiny.starter.worker.SchedulerWorkerProperties;
import net.xo68.destiny.starter.worker.handler.JobHandleReplyProvider;
import net.xo68.destiny.starter.worker.handler.JobHandler;
import net.xo68.destiny.starter.worker.handler.JobHandlerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 任务处理器工厂实现
 * @author wuxie
 * @version 2020-10-28
 */
@Slf4j
@Component
public class JobHandlerFactoryImpl implements JobHandlerFactory,ApplicationContextAware, SmartInitializingSingleton {

    private final ConcurrentMap<String, JobHandler> jobHandlerRepository = new ConcurrentHashMap<>();

    private final DefaultJobHandler defaultJobHandler;

    public JobHandlerFactoryImpl(SchedulerWorkerProperties schedulerWorkerProperties, JobHandleReplyProvider jobHandleReplyProvider, DatagramSerializer datagramSerializer) {
        this.defaultJobHandler=new DefaultJobHandler(schedulerWorkerProperties,jobHandleReplyProvider,datagramSerializer);
    }

    private static ApplicationContext applicationContext=null;

    @Override
    public Set<String> getHandleNames(){
        return this.jobHandlerRepository.keySet();
    }

    @Override
    public JobHandler getJobHandler(String jobHandlerName) {
        return this.jobHandlerRepository.getOrDefault(jobHandlerName,defaultJobHandler);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        JobHandlerFactoryImpl.applicationContext=applicationContext;
    }

    @Override
    public void afterSingletonsInstantiated() {
        initJobHandlerRepository();
    }

    private void initJobHandlerRepository() {
        if (applicationContext == null) {
            return;
        }
        // init job handler action
        Map<String, JobHandler> serviceBeanMap = applicationContext.getBeansOfType(JobHandler.class);

        if (CollectionUtil.isNotEmpty(serviceBeanMap)) {
            for (Map.Entry<String, JobHandler> jobHandlerBean : serviceBeanMap.entrySet()) {
                this.jobHandlerRepository.put(jobHandlerBean.getKey(),jobHandlerBean.getValue());
            }
        }
    }
}
